
var queryUtil = require('./query.js');
var events = require('events');

function toArray(str) {
  if(str) {
    return str.split(',');
  }
}

var c = {
 create:function (Model, uniqueKey, queryKey) {

  console.log("uniqueKey:" + uniqueKey);

 	if (null == uniqueKey) {
 		uniqueKey = "_id";
 	}

// var dataPicker = require("../dataPicker")(properties);

var ctlr = {};

ctlr.limit = function(entity, req, res) {
  return entity;
}

var handleErr = function(err, res){
    res.send({'code': 1000, message: err});
}
function getDefConfition(req){

  console.log('uniqueKey:' + uniqueKey);
  console.log('uniqueKey-value:' + req.params[uniqueKey]);

	var condition = {};
  condition[uniqueKey] = req.params[uniqueKey];

  return condition;
}

ctlr.post = function(req, res){
  console.log("accept post request.");
  console.log(req.body);

  var entity = new Model(req.body);

  // dataPicker.fromRequest(req, entity);

  entity.save(function(err){
     if (err) {
        handleErr(err, res);
        return;
      }

      res.json({code: 0, message: 'added!', data: entity });

  });


};
ctlr.patch = function(req, res) {

  console.log("accept patch request:" + req.params[uniqueKey]);

  var data = req.body;

  console.log("picked data:" + JSON.stringify(data));

  var condition = getDefConfition(req);

  inernalPatch(condition, data,  function (err, data){
    if (err) {
      handleErr(err, res);
      return;
    }
    if (null == data) {
      res.json({code: 1000, message: "没有找到数据:["+req.params.code+"]"});
      return;
    }

    res.json({code: 0, data: data});
  });
};


ctlr.getList = function(req, res) {
   console.log("get List.");

  var condition = queryUtil.getCondition(req, queryKey);

  var find = Model.find(ctlr.limit(condition));

  find = queryUtil.wrapFind(find,req).select().sort()/*.paginate()*/.find;

  //prepare emitter
  var emitter = new events.EventEmitter();
  var after = function(times, callback){
    var count = 0, results = {};
    return function(key, value){
      results[key] = value;
      count ++;
      if(count == times){
        callback(results);
      }
    }
  }
  var done = after(2, function(results){
    //handle err

    res.json({code: 0, data: results.data, count: results.count});
  });

  emitter.on('done', done);


  //do what you want.
  var callback =  function(err, datas) {
    if (err) {
      handleErr(err, res);
      return;
    }
    emitter.emit('done', 'data', datas);
  }
  find.exec(callback);

  Model.count(condition, function(err, count){
    if (err) {
      handleErr(err, res);
      return;
    }
    emitter.emit('done', 'count', count);
  });



};

ctlr.deleteList = function(req, res) {

  console.log("accept delete list request.");

  Model.remove(
  ctlr.limit({}),
  function(err, num) {
     if (err) {
      handleErr(err, res);
      return;
    }

    res.json({code: 0, message: num  + ' removed!' });
  });
};


ctlr.delete = function(req, res) {


  console.log("accept delete request.");

  var condition = getDefConfition(req);

  console.log("condition: " + JSON.stringify(condition));

  Model.remove(
  ctlr.limit(condition),
  function(err, num) {
    if (err) {
      handleErr(err, res);
      return;
    }

    res.json({code: 0,  message: num  + ' removed!'});
  });
};


ctlr.get = function(req, res) {

  var condition = getDefConfition(req);
  condition = ctlr.limit(condition);

  Model.findOne(condition, function(err, data){

    if (err) {
      handleErr(err, res);
      return;
    }
    if (data) {
      res.json({code: 0, data:data});
    } else {
      res.send({code: 1000, message: "not found data with condition: "+JSON.stringify(condition)+""});
    }
  });
};

ctlr.put = function(req, res) {

  var data = req.body;

  console.log("picked data:" + JSON.stringify(data));

  var condition = getDefConfition(req);

  inernalPatch(condition, data,  function (err, data){
    if (err) {
      handleErr(err, res);
      return;
    }

    res.json({code: 0, data: data});
  });
};


var inernalPatch = function(condition, update, callback){

  update.updateTime = Date.now();

  /*
  delete update._id;
  delete update._v;
  */

  Model.findOneAndUpdate(
    ctlr.limit(condition),
    update,
    function(err, data) {
      callback(err, data);
    }
  );

}

var inernalGetList = function(condition, callback){
  Model.find(
  ctlr.limit(condition),
  function(err, datas) {
     if (err) {
      callback.call(this, err);
      return;
    }
    callback.call(this, null, datas);
  });
}


ctlr.localGetList = inernalGetList;

ctlr.localGet = function (condition, callback) {

  Model.findOne(condition, function(err, data){
    callback(err, data);
  });
}

ctlr.localPatch = function (condition, update,callback){
  inernalPatch(condition, update, callback);
}

return ctlr;
}
};

exports.api = function(Model, properties, queryKey) {
  var ctlr = c.create(Model, properties, queryKey||[]);
  return ctlr;
};
